package com.zhanyd.app.service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.zhanyd.app.common.ApiResult;
import com.zhanyd.app.common.util.HttpService;
import com.zhanyd.app.common.util.MD5Generate;
import com.zhanyd.app.common.util.StringHelp;

@Component  
public class ModBusSchedulerService {

	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	
	@Scheduled(cron="0/10 * * * * ?")  //1秒
    public void modBusScheduler(){   
		//是否需要加水
		/*if(isNeedWaterQuantity()){
			//获取桶号
			String PailNo = getPailNo();
			System.out.println(PailNo);
			//获取加水量
			String waterQuantity = getWaterByPailNo(PailNo);
			//写加水量数据
			writeWaterQuantity("876.23");
			//writeWaterQuantity(waterQuantity);
		}*/
		
		//获取桶号
		String PailNo = "1100001";
		System.out.println(PailNo);
		//获取加水量
		String waterQuantity = getWaterByPailNo(PailNo);
		//写加水量数据
		//writeWaterQuantity("876.23");
		writeWaterQuantity(waterQuantity);
	}
	
	
	/**
	 * 是否需要加水
	 * @return
	 */
	public boolean isNeedWaterQuantity(){
		byte[] sendData = getSendByteRead((byte)3,11,1);
		byte[] dataArray = operateModbus(sendData);
		if(dataArray != null && dataArray.length > 0){
			String binaryStr = Integer.toBinaryString((dataArray[0] & 0xFF) + 0x100).substring(1);
			logger.info("状态位:" + binaryStr);
			//System.out.println(Integer.toBinaryString((dataArray[0] & 0xFF) + 0x100).substring(1));
			//System.out.println(Integer.toBinaryString((dataArray[1] & 0xFF) + 0x100).substring(1));
			if("1".equals(binaryStr.substring(0, 1))){
				logger.info("已加水");
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 读取桶编号
	 * @return
	 */
	public String getPailNo(){
		byte[] sendData = getSendByteRead((byte)3,0,6);
		byte[] dataArray = operateModbus(sendData);
		return dataArray == null ? null : new String(dataArray);
	}
    
    
    
    /**
     * 获取加水量
     * @param pailNo
     * @return
     */
    public String getWaterByPailNo(String pailNo){
    	logger.info("getWaterByPailNo begin");
    	if(StringHelp.isEmpty(pailNo)){
    		return "";
    	}

    	JSONObject param = new JSONObject();
    	JSONObject head = new JSONObject();
    	JSONObject data = new JSONObject();
    	//构造签名
    	long currentTime = System.currentTimeMillis();
    	String psw = MD5Generate.getMD5("FBL7Zc3l".getBytes());
    	String beforeSign = "getWaterByPailNo" + currentTime + psw.toLowerCase();
    	String sign = MD5Generate.getMD5(beforeSign.getBytes());
    	
    	head.put("company_num", "10581");
    	head.put("key", currentTime);
    	head.put("sign", sign.toUpperCase());
    	//桶编号
    	data.put("pail_no", pailNo);
    	//api地址
    	String url = "http://www.kmzhyf.cn:8192/zyf/service/waterService/getWaterByPailNo";
    	param.put("head",head);
    	param.put("data",data);
    	String result = HttpService.post(url, param.toJSONString());
    	logger.info(result);
    	System.out.println(result);
    	JSONObject resultJson =  JSONObject.parseObject(result);
    	JSONObject resultData;
    	if("0".equals(resultJson.getString("resultCode"))){
    		resultData = resultJson.getJSONObject("data");
    		logger.info("加水量: " + resultData.getString("water_quantity"));
    		return resultData.getString("water_quantity");
    	}else{
    		logger.info("出错啦: " + resultJson.getString("description"));
    		return "";
    	}
    }
    
    /**
     * 写加水量数据
     * @param waterQuantity
     */
    public void writeWaterQuantity(String waterQuantity){
    	if(!StringHelp.isEmpty(waterQuantity)){
    		//处理浮点数
    		/*Float waterQuantityf = Float.valueOf(waterQuantity);
    		System.out.println("转换后的16进制：" + Integer.toHexString(Float.floatToIntBits(waterQuantityf)));
    		byte[] numData = hexToBytes(Integer.toHexString(Float.floatToIntBits(waterQuantityf)));*/
    		
    		//处理整数
    		int waterQuantityf = Integer.valueOf(waterQuantity);
    		System.out.println("转换后的16进制：" + Integer.toHexString(waterQuantityf));
    		byte[] numData = IntToByteBigEndiam(waterQuantityf);
    		System.out.print("转换后的字节数组：");
    		//Stream.of(numData).forEach(d->System.out.print(Integer.toHexString((d&0xFF))));
    		for (byte b : numData) {
    			System.out.print(b + " ");
			}
    		System.out.println();
    		//写多个寄存器
    		byte[] sendData = new byte[]{
    				0x00,0x01,0x00,0x00,0x00,0x0B,0x01,0x10,0x00,0x00,0x00,0x02,0x04,numData[0],numData[1],numData[2],numData[3]
    		};
    		byte[] resultData = operateModbus(sendData);
    		if(resultData == null){
    			logger.info("加水:" + waterQuantityf + " 失败");
    		}else{
    			logger.info("加水:" + waterQuantityf + " 成功");
    		}
    	}else{
    		logger.info("加水量为空");
    	}
    }
    
    
    /**
     * 读写操作	
     */
	 public byte[] operateModbus(byte[] sendData) {

			int port = 502;
			//String server = "localhost";
			String server = "192.168.0.1";
			Socket socket = null;
			
			OutputStream output = null;
			InputStream input = null;
			
			byte[] dataArray;
			
			// connect to server
			try {
			    socket = new Socket(server, port);
			    System.out.println("\nConnected with server " + socket.getInetAddress() + ":" + socket.getPort());
			
			  System.out.println("客户端发送: ");
			    for(byte item : sendData){
			    	System.out.print(item + " ");
			    }
			    output = socket.getOutputStream();
			    output.write(sendData);
			    //output.flush();
			    input = socket.getInputStream(); 
				byte[] returnArray = new byte[50];
			    input.read(returnArray , 0, 50);
			    //第9位是数据位的长度
			    int dataLength = returnArray[8];
			    dataArray = new byte[dataLength];
			    System.out.println("\n客户端接收: ");
			    for(byte item : returnArray){
			    	System.out.print(item + " ");
			    }
			    System.out.println("\n数据域: ");
			    int k = 0;
			    for(int i= 9; i < dataLength + 9; i++){
			    	System.out.print(returnArray[i] + " ");
			    	dataArray[k] = returnArray[i];
			    	k++;
			    }
			    return dataArray;
			}
			catch (IOException e) {
			    System.out.println(e);
			    return null;
			}
			finally{
				try {
					if(output != null){
						output.close();
					}
					if(socket != null){
						socket.close();
					}
					if(input != null){
						input.close();
					}
				}
				catch (IOException e) {
					System.out.println(e);
				}
			}
	}
	 
	/**
	 * 读数据
	 * @param function
	 * @param address
	 * @param count
	 * @return
	 */
	public byte[] getSendByteRead(byte function,int address,int count) {
		return new byte[]{
			0x00, 0x01, 0x00, 0x00, 0x00, //tcp 的头, 默认不变
			0x06,     //字节长度
			0x01,     //默认服务器
			function, //功能号 0-5 读取为3
			(byte)(address >> 8), (byte)(address & 0x00ff), //起始地址
			(byte)(count >> 8), (byte)(count & 0x00ff)     //获取的word数量
		};
	}
	
	/**
	 * 写数据
	 * @param function
	 * @param address
	 * @param hight
	 * @param low
	 * @return
	 */
	public byte[] getSendByteWriteSigle(byte function,int address,byte hight,byte low) {
		return new byte[]{
			0x00, 0x01, 0x00, 0x00, 0x00, //tcp 的头, 默认不变
			0x06,     //字节长度
			0x01,     //默认服务器
			function, //功能号 0-5 读取为3
			(byte)(address >> 8), (byte)(address & 0x00ff), //起始地址
			hight, low     //设置的值
		};
	}
	
	/**
	 * 写多个线圈
	 * @param function
	 * @param address
	 * @param hight
	 * @param low
	 * @return
	 */
	public byte[] getSendByteWriteMultiCoils(byte function,int address,int writeCount,byte byteCount,byte hight,byte low) {
		return new byte[]{
			0x00, 0x01, 0x00, 0x00, 0x00, //tcp 的头, 默认不变
			0x09,     //字节长度
			0x01,     //默认服务器
			function, //功能号 0-5 读取为3
			(byte)(address >> 8), (byte)(address & 0x00ff), //起始地址
			(byte)(writeCount >> 8), (byte)(writeCount & 0x00ff), //输出数量
			byteCount, //字节数
			hight, low     //设置的值
		};
	}
	
	/**
	 * byte转int大头模式
	 * @param byteData
	 * @return
	 */
	public int byteToIntBigEndian(byte[] byteData){
		return (
				(byteData[0] << 24) |
				((byteData[1] & 0xFF) << 16) |
				((byteData[2] & 0xFF) << 8) |
				((byteData[3] & 0xFF) )
				);
	}
	
	
	/**
	 * int转字节数组大头模式
	 * @param intData
	 * @return
	 */
	public byte[] IntToByteBigEndiam(int intData){
		byte[] resultBytes = new byte[4];
		resultBytes[0] = (byte)((intData >> 24) & 0xFF);
		resultBytes[1] = (byte)((intData >> 16) & 0xFF);
		resultBytes[2] = (byte)((intData >> 8) & 0xFF);
		resultBytes[3] = (byte)(intData & 0xFF);
		return resultBytes;
	}
	
	
	/**
    * 将16进制字符串转换为byte[]
    * 
    * @param str
    * @return
    */
   public byte[] hexToBytes(String str) {
       if(str == null || str.trim().equals("")) {
           return new byte[0];
       }

       byte[] bytes = new byte[str.length() / 2];
       for(int i = 0; i < str.length() / 2; i++) {
           String subStr = str.substring(i * 2, i * 2 + 2);
           bytes[i] = (byte) Integer.parseInt(subStr, 16);
       }

       return bytes;
   }
}
